package com.zkjl.protect_business.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.crypto.digest.DigestAlgorithm;
import cn.hutool.crypto.digest.Digester;
import cn.hutool.json.JSONUtil;
import com.google.common.collect.Lists;
import com.zkjl.protect_business.common.BaseException;
import com.zkjl.protect_business.common.Status;
import com.zkjl.protect_business.common.UserThreadLocal;
import com.zkjl.protect_business.dto.PageBaseDTO;
import com.zkjl.protect_business.dto.PageDTO;
import com.zkjl.protect_business.dto.PermissionDTO;
import com.zkjl.protect_business.dto.SortDTO;
import com.zkjl.protect_business.entity.Business;
import com.zkjl.protect_business.entity.Permission;
import com.zkjl.protect_business.entity.User;
import com.zkjl.protect_business.repository.PermissionRepository;
import com.zkjl.protect_business.repository.UserRepository;
import com.zkjl.protect_business.service.BusinessService;
import com.zkjl.protect_business.service.LogService;
import com.zkjl.protect_business.service.PermissionService;
import com.zkjl.protect_business.utils.QueryUtil;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import static com.zkjl.protect_business.common.Consts.*;

@Service
public class PermissionServiceImpl implements PermissionService {

    @Autowired
    ModelMapper modelMapper;
    @Autowired
    PermissionRepository permissionRepository;

    @Autowired
    ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Autowired
    LogService logService;
    @Autowired
    UserRepository userRepository;

    @Autowired
    BusinessService businessService;

    private Digester md5 = new Digester(DigestAlgorithm.MD5);

    @Override
    public Permission saveOrUpdate(PermissionDTO permissionDTO, String id) {

        Permission permission = modelMapper.map(permissionDTO, Permission.class);

        if (StringUtils.isBlank(id)) {
            Digester md5 = new Digester(DigestAlgorithm.MD5);
            id = md5.digestHex(JSONUtil.toJsonStr(permission));
            permission.setId(id);
            permission.setBaseInfo();

            logService.save("权限", permission.getName(), OPERATION_ADD);

        }else {
            permission.setId(id);
            logService.save("权限", permission.getName(), OPERATION_EDIT);
        }

        Permission save = permissionRepository.save(permission);

        return save;
    }

    @Override
    public Boolean del(String id) {

        Permission permission = get(id);
        String name = permission.getName();
        logService.save("权限", name, OPERATION_DEL);
        permissionRepository.deleteById(id);

        return true;
    }

    @Override
    public Permission get(String id) {

        Optional<Permission> repository = permissionRepository.findById(id);
        if (!repository.isPresent()) {
            throw new BaseException(Status.DATA_NOT_EXIST, "未找到权限信息！");
        }
        Permission permission = repository.get();

        return permission;
    }

    @Override
    public List<Permission> list() {

        Iterable<Permission> allPermissions = permissionRepository.findAll();
        List<Permission> permissions = Lists.newArrayList(allPermissions);


        return permissions;
    }

    @Override
    public Permission create(String businessId, List<String> orgIds) {

        Business business = businessService.get(businessId);
        String pid = business.getPid();
        String name = business.getName();

        //新增权限信息

        String permissionId = md5.digestHex(businessId);

        String routing = business.getRouting();
        //给参与单位的几个基础权限
        Permission uploadDocument = null;
        Permission query = null;
        Permission permission = null;


        if (StringUtils.isEmpty(routing)){
            return null;
        }

        //非自定义的业务
        PermissionDTO permissionDTO = new PermissionDTO();
        permissionDTO.setType(1);   //菜单
        permissionDTO.setParentId("0");
        if (StringUtils.isNotBlank(pid) && "business".equals(routing)) { //仅通用业务才生产下面这些按钮
            String permissionPid = md5.digestHex(pid);

            permissionDTO.setParentId(permissionPid);
            //生成按钮
            uploadDocument = saveBtn(permissionId, businessId, "uploadDocument", name + "-上传文档");
            saveBtn(permissionId, businessId, "edit", name + "-编辑");
            saveBtn(permissionId, businessId, "createArchive", name + "-创建存档");
            saveBtn(permissionId, businessId, "del", name + "-删除");
            query = saveBtn(permissionId, businessId, "query", name + "-查询");
            saveBtn(permissionId, businessId, "uploadTemplate", name + "-上传模板");
            saveBtn(permissionId, businessId, "export", name + "-导出");
        }

        permissionDTO.setName(name);
        permissionDTO.setPermission("page:" + businessId);
        permission = saveOrUpdate(permissionDTO, permissionId);

        //为当前用户添加这个权限
        User user = UserThreadLocal.get();
        if (user != null) {
            List<Permission> permissions = user.getPermissions();
            permissions.add(permission);
            userRepository.save(user);
        }


        //给参与机构下面的所有用户追加权限
        if (CollUtil.isNotEmpty(orgIds)) {

            Permission finalPermission = permission;
            Permission finalQuery = query;
            Permission finalUploadDocument = uploadDocument;

            List<User> users = userRepository.findAllByOrgIdIn(orgIds);
            if (CollUtil.isNotEmpty(users)) {
                users.stream().forEach(user1 -> {
                    List<Permission> permissions1 = user1.getPermissions();
                    permissions1.add(finalPermission);
                    permissions1.add(finalQuery);
                    permissions1.add(finalUploadDocument);
                    userRepository.save(user1);
                });
            }
        }


        return permission;

    }



    /**
     * 保存按钮权限
     *
     * @param pid
     * @param operation
     */
    public Permission saveBtn(String pid, String name, String operation, String operationName) {

        PermissionDTO permissionDTO = new PermissionDTO();
        String type = "btn:";
        permissionDTO.setType(2);   //按钮
        permissionDTO.setParentId(pid);
        permissionDTO.setName(operationName);
        permissionDTO.setPermission(type + name + ":" + operation);

        Permission permission = saveOrUpdate(permissionDTO, null);

        //为当前用户添加这个权限
        User user = UserThreadLocal.get();
        if (user != null) {
            List<Permission> permissions = user.getPermissions();
            permissions.add(permission);
        }


        return permission;


    }





    @Override
    public PageImpl page(PageBaseDTO pageBaseDTO, SortDTO sortDTO) {

        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        BoolQueryBuilder qb = QueryBuilders.boolQuery();

        Pageable pageable = QueryUtil.build(qb, queryBuilder, pageBaseDTO, sortDTO, Permission.class);

        queryBuilder.withQuery(qb);

        SearchHits<Permission> search1 = elasticsearchRestTemplate.search(queryBuilder.build(), Permission.class);
        List<Permission> collect = search1.stream().map(SearchHit::getContent).collect(Collectors.toList());
        long total = search1.getTotalHits();

        PageImpl page = new PageImpl(collect, pageable, total);

        return page;
    }

    @Override
    public Boolean delByBusinessId(String businessId) {


        String permissionId = md5.digestHex(businessId);

        permissionRepository.deleteAllByParentId(permissionId);
        permissionRepository.deleteById(permissionId);


        return true;
    }


}
